#include "fiche.h"

Fiche* nouvelle_fiche()
{
    Fiche* fiche = (Fiche*) malloc(sizeof(Fiche));
    fiche->label[0] = 0;
    fiche->description[0] = 0;
    fiche->objectif[0] = 0;
    fiche->recompense[0] = 0;

    fiche->precedent = NULL;
    fiche->suivant = NULL;
    fiche->secondaire = NULL;

    fiche->quest = 0;
    fiche->etape = 0;

    return fiche;
}

void supprimer_fiche(Fiche* fiche)
{
    free(fiche);
}

void supprimer_quete(Fiche* fiche)
{
    supprimer_quete(fiche->suivant);
    supprimer_fiche(fiche);
}

void supprimer_fiches(Fiche* fiches)
{
    if(fiches != NULL)
    {
        supprimer_fiches(fiches->suivant);
        supprimer_fiches(fiches->secondaire);

        supprimer_fiche(fiches);
    }
}

Fiche* get_fiche(Fiche* fiches, int quest, int etape)
{
    if(fiches == NULL)
        return NULL;
    if(fiches->quest == quest)
    {
        if(fiches->etape == etape)
            return fiches;
        else
            return get_fiche(fiches->suivant, quest, etape);

    }

    // On n'est pas dans la bonne quete
    Fiche* retour_quete = get_fiche(fiches->suivant, quest, etape);
    if(retour_quete != NULL)
        return retour_quete;
    return get_fiche(fiches->secondaire, quest, etape);
}

// Reindexation faite
int ajouter_quete_secondaire_by_id(Fiche* fiches, int quest, int etape, Fiche* fiche)
{
    Fiche* pere = get_fiche(fiches, quest, etape);
    if(pere == NULL)
        return 0;
    ajouter_quete_secondaire(pere, fiche);

    reindexer_etapes_quetes(fiches);
    return 1;
}

int ajouter_etape_avant_by_id(Fiche** fiches, int quest, int etape, Fiche* fiche)
{

    Fiche* curseur = get_fiche(*fiches, quest, etape);
    if(curseur == NULL)
        return 0;

    ajouter_etape_avant(curseur, fiche);
    if(quest == 0 && etape == 0)
        *fiches = fiche;

    reindexer_etapes_quetes(*fiches);
    return 1;
}

int ajouter_etape_apres_by_id(Fiche* fiches, int quest, int etape, Fiche* fiche)
{
    Fiche* curseur = get_fiche(fiches, quest, etape);
    if(curseur == NULL)
        return 0;

    ajouter_etape_apres(curseur, fiche);

    reindexer_etapes_quetes(fiches);
    return 1;
}

int changer_pere_by_id(Fiche* fiches, int quest, int p_quest, int p_etape)
{
    if(quest == 0 || quest == p_quest)
        return 0;
    Fiche* quete = get_fiche(fiches, quest, 0);
    Fiche* futur_pere = get_fiche(fiches, quest, 0);
    if(quete == NULL || futur_pere == NULL)
        return 0;

    ajouter_quete_secondaire_fin(quete, futur_pere->secondaire);

    futur_pere->secondaire = quete;
    quete->precedent = futur_pere;

    reindexer_etapes_quetes(fiches);

    return 1;
}

int supprimer_fiche_by_id(Fiche** fiches, int quest, int etape)
{
    if(quest == 0 && etape == 0)
    {
        if((*fiches)->suivant == NULL)
            return 0;
        Fiche* to_keep = (*fiches)->suivant;
        to_keep->precedent = NULL;
        // On s occupe des quetes secondaires
        ajouter_quete_secondaire_fin(to_keep, (*fiches)->secondaire);
        supprimer_fiche(*fiches);
        *fiches = to_keep;

        reindexer_etapes_quetes(*fiches);
        return 1;
    }


    Fiche* a_supprimer = get_fiche(*fiches, quest, etape);
    if(a_supprimer == NULL)
        return 0;

    // Il faut reaffecter le secondaire
    ajouter_quete_secondaire_fin(a_supprimer->precedent, a_supprimer->secondaire);

    a_supprimer->precedent->suivant = a_supprimer->suivant;
    if(a_supprimer->suivant != NULL)
        a_supprimer->suivant->precedent = a_supprimer->precedent;
    supprimer_fiche(a_supprimer);

    reindexer_etapes_quetes(*fiches);
    return 1;
}

int supprimer_quete_by_id(Fiche* fiches, int quest)
{
    if(quest == 0)
        return 1;
    Fiche* a_supprimer = get_fiche(fiches, quest, 0);
    if(a_supprimer == NULL)
        return 1;
    Fiche* pere = a_supprimer->precedent;
    Fiche* buffer;
    while(a_supprimer != NULL)
    {
        buffer = a_supprimer->suivant;
        ajouter_quete_secondaire_fin(pere, buffer->secondaire);
        supprimer_fiche(buffer);
        a_supprimer = buffer;
    }

    reindexer_etapes_quetes(fiches);

    return 1;
}

// Reindexation non faite
void ajouter_quete_secondaire(Fiche* pere, Fiche* fiche)
{
    if(fiche != NULL)
    {
        ajouter_quete_secondaire_fin(fiche, pere->secondaire);
        fiche->precedent = pere;
        pere->secondaire = fiche;
    }
}
void ajouter_quete_secondaire_fin(Fiche* pere, Fiche* fiche)
{
    if(fiche != NULL)
    {
        Fiche* dernier = pere;
        while(dernier->secondaire != NULL)
            dernier = dernier->secondaire;
        fiche->precedent = dernier;
        dernier->secondaire = fiche;
    }
}

void ajouter_etape_avant(Fiche* curseur, Fiche* fiche)
{
    fiche->suivant = curseur;
    fiche->precedent = curseur->precedent;

    if(curseur->precedent== NULL || curseur->precedent->quest != curseur->quest) // Si c'est le premier d'une quete, on change les sous-quetes
    {
        fiche->secondaire = curseur->secondaire;
        curseur->secondaire = NULL;
    }

    if(curseur->precedent != NULL)
        curseur->precedent->suivant = fiche;
    curseur->precedent = fiche;
}

void ajouter_etape_apres(Fiche* curseur, Fiche* fiche)
{
    fiche->suivant = curseur->suivant;
    fiche->precedent = curseur;
    fiche->secondaire = NULL;

    if(curseur->suivant != NULL)
        curseur->suivant->precedent = fiche;
    curseur->suivant = fiche;
}

void reindexer_etapes_quetes(Fiche* fiches)
{
    int quete_max = 0;
    r_reindexer_etapes_quetes(fiches, 0, 0, &quete_max);
}

void r_reindexer_etapes_quetes(Fiche* fiches, int quete, int etape, int* quete_max)
{
    if(fiches != NULL)
    {
        if(quete == *quete_max)
            (*quete_max)++;
        fiches->quest = quete;
        fiches->etape = etape;
        r_reindexer_etapes_quetes(fiches->suivant, quete, etape+1, quete_max);
        r_reindexer_etapes_quetes(fiches->secondaire, (*quete_max), 0, quete_max);
    }
}
